<template>
  <div class="word-list-container">
    <!-- 顶部导航栏 -->
    <div class="header">
      <h1 class="title">单词列表</h1>
      <div class="header-actions">
        <!-- 语音选择下拉框 -->
        <div class="voice-selection">
          <label for="voice-select">选择语音：</label>
          <select id="voice-select" v-model="selectedVoice" class="voice-select">
            <option v-for="(voiceName, voiceId) in availableVoices" :key="voiceId" :value="voiceId">
              {{ voiceName }}
            </option>
          </select>
        </div>
        <!-- 是否拼读选择框 -->
        <div class="spell-selection">
          <label for="spell-select">是否拼读：</label>
          <select id="spell-select" v-model="shouldSpellOut" class="spell-select" @change="handleSpellOutChange">
            <option :value="0">普通发音</option>
            <option :value="1">字母拼读</option>
          </select>
        </div>
        <button class="btn-add" @click="goToAddWord">
          + 添加
        </button>
      </div>
    </div>

    <!-- 搜索和筛选区域 -->
    <div class="search-filter-section">
      <div class="search-box">
        <span class="search-icon">🔍</span>
        <input 
          type="text" 
          v-model="searchKeyword" 
          placeholder="搜索单词..." 
          class="search-input"
          @input="handleSearch"
        />
        <button 
          v-if="searchKeyword"
          class="clear-search-btn" 
          @click="clearSearch"
        >
          ✕
        </button>
      </div>
      
      <div class="filter-options">
        <select v-model="currentWordSet" class="filter-select" @change="handleWordSetChange">
          <option v-for="set in wordSets" :key="set" :value="set">{{ set }}</option>
        </select>
        <div class="sort-options">
          <button 
            :class="['sort-btn', { active: sortBy === 'alphabetical' }]"
            @click="sortBy = 'alphabetical'"
          >
            字母排序
          </button>
          <button 
            :class="['sort-btn', { active: sortBy === 'recent' }]"
            @click="sortBy = 'recent'"
          >
            最近学习
          </button>
        </div>
      </div>
    </div>

    <!-- 单词列表 -->
    <div class="word-list" v-if="words.length > 0">
      <div 
        class="word-item" 
        v-for="word in displayedWords" 
        :key="word.id"
        @click="goToWordDetail(word.id)"
      >
        <div class="word-main">
          <div class="word-content">
            <span class="word-text">{{ word.content }}</span>
            <span class="word-phonetic" v-if="word.phonetic">{{ word.phonetic }}</span>
          </div>
          <span class="word-translation">{{ word.translation }}</span>
        </div>
        <div class="word-actions">
          <button class="btn-pronounce" @click.stop="playPronunciation(word)">
            🔊
          </button>
          <button class="btn-more" @click.stop="showMoreOptions(word)">
            ⋯
          </button>
        </div>
      </div>
    </div>

    <!-- 空状态 -->
    <div class="empty-state" v-else>
      <div class="empty-icon">📝</div>
      <p class="empty-text">暂无单词</p>
      <p class="empty-subtext">点击右上角添加单词开始学习</p>
    </div>

    <!-- 加载更多 -->
    <div class="load-more" v-if="words.length > 0 && hasMore">
      <p v-if="!isLoading" @click="loadMore">上拉加载更多</p>
      <p v-else>加载中...</p>
    </div>

    <!-- 操作菜单 -->
    <div v-if="showPopup" class="modal-overlay" @click="closeActionPopup">
      <div class="popup-content" @click.stop>
        <div class="popup-header">
          <h3 class="popup-title">操作选项</h3>
          <button class="close-popup-btn" @click="closeActionPopup">
            ✕
          </button>
        </div>
        <div class="popup-actions">
          <button class="popup-action-item" @click="handleEditWord">
            <span class="action-icon">✏️</span>
            <span>编辑单词</span>
          </button>
          <button class="popup-action-item" @click="handleAddToWordSet">
            <span class="action-icon">➕</span>
            <span>添加到单词集</span>
          </button>
          <button class="popup-action-item danger" @click="handleDeleteWord">
            <span class="action-icon">🗑️</span>
            <span>删除单词</span>
          </button>
        </div>
        <button class="cancel-btn" @click="closeActionPopup">取消</button>
      </div>
    </div>
  </div>
</template>

<script>
import { ref, computed, onMounted, onUnmounted, watch } from 'vue'
import { useUserStore } from '../../store'
import { useRouter } from 'vue-router'
import { loadHunspellRules, getWordPhoneticSpelling } from '../../utils/hunspellUtils.js'
import { wordAPI } from '../../services/apiService'

export default {
  name: 'WordList',
  setup() {
    const userStore = useUserStore()
    const router = useRouter()
    
    // 状态管理
    const words = ref([])
    const searchKeyword = ref('')
    const sortBy = ref('alphabetical')
    const currentWordSet = ref('全部单词')
    const wordSets = ref(['全部单词', '我的收藏', '学习计划'])
    const currentPage = ref(1)
    const pageSize = ref(20)
    const hasMore = ref(true)
    const isLoading = ref(false)
    const selectedWord = ref(null)
    const showPopup = ref(false)
    
    // 语音相关状态
    const availableVoices = ref({
      'expr-voice-5-m': 'Male Voice 5 (默认)',
      'expr-voice-5-f': 'Female Voice 5',
      'expr-voice-2-m': 'Male Voice 2',
      'expr-voice-2-f': 'Female Voice 2',
      'expr-voice-3-m': 'Male Voice 3',
      'expr-voice-3-f': 'Female Voice 3',
      'expr-voice-4-m': 'Male Voice 4',
      'expr-voice-4-f': 'Female Voice 4'
    })
    const selectedVoice = ref('expr-voice-5-m') // 默认使用Male Voice 5
    const shouldSpellOut = ref(0) // 默认不使用拼读功能(0=普通发音, 1=字母拼读)
    
    // 添加change事件处理程序以确保值被正确更新
    const handleSpellOutChange = (event) => {
      const value = parseInt(event.target.value);
      console.log('选择框change事件触发，新值:', value);
      shouldSpellOut.value = value;
      localStorage.setItem('shouldSpellOut', value.toString());
    };
    
    // 初始化值
    shouldSpellOut.value = parseInt(localStorage.getItem('shouldSpellOut')) || 0;
    console.log('shouldSpellOut初始化值:', shouldSpellOut.value);
    
    // 监控shouldSpellOut的变化
    watch(shouldSpellOut, (newValue) => {
      console.log('shouldSpellOut值已更新:', newValue);
      localStorage.setItem('shouldSpellOut', newValue.toString());
    });
    
    // 显示的单词列表（根据搜索和排序过滤）
    const displayedWords = computed(() => {
      let filtered = [...words.value]
      
      // 搜索过滤
      if (searchKeyword.value.trim()) {
        const keyword = searchKeyword.value.toLowerCase().trim()
        filtered = filtered.filter(word => 
          word.content.toLowerCase().includes(keyword) || 
          word.translation.toLowerCase().includes(keyword)
        )
      }
      
      // 排序
      if (sortBy.value === 'alphabetical') {
        filtered.sort((a, b) => a.content.localeCompare(b.content))
      } else if (sortBy.value === 'recent') {
        filtered.sort((a, b) => new Date(b.updatedAt) - new Date(a.updatedAt))
      }
      
      return filtered
    })
    
    // 加载单词列表
    const loadWords = async (refresh = false) => {
      if (isLoading.value) return
      
      if (refresh) {
        currentPage.value = 1
        hasMore.value = true
        words.value = []
      }
      
      isLoading.value = true
      
      // 确保即使API调用失败，也能显示模拟数据
      try {
        // 优先尝试调用后端API获取数据
        console.log('尝试调用真实API获取单词列表...')
        
        // 构建请求参数
        const params = {
          page: currentPage.value,
          pageSize: pageSize.value
        }
        
        if (currentWordSet.value !== '全部单词') {
          params.wordSet = currentWordSet.value
        }
        
        // 设置超时时间为5秒
        const apiTimeout = new Promise((_, reject) => {
          setTimeout(() => reject(new Error('API调用超时')), 5000)
        })
        
        // 竞争Promise，确保API调用不会无限等待
        const response = await Promise.race([
          wordAPI.getWords(params),
          apiTimeout
        ])
        
        console.log('API调用成功，返回数据:', response)
        
        // 处理API返回的数据
        const wordData = Array.isArray(response) ? response : (response.data || [])
        
        if (refresh) {
          words.value = wordData
        } else {
          words.value = [...words.value, ...wordData]
        }
        
        hasMore.value = wordData.length === pageSize.value
        
        console.log('成功加载单词数量:', wordData.length)
      } catch (error) {
        console.error('加载单词列表失败:', error)
        
        // 无论何种错误，都使用模拟数据作为备选
        console.log('API调用失败，立即使用模拟数据作为备选')
        const mockResponse = generateMockWords()
        
        if (refresh || words.value.length === 0) {
          words.value = mockResponse
        } else {
          words.value = [...words.value, ...mockResponse]
        }
        
        hasMore.value = mockResponse.length === pageSize.value
        
        // 仅在控制台显示错误信息，不弹出alert影响用户体验
        let errorMsg = '无法连接到后端服务，使用本地模拟数据'
        if (error.response) {
          errorMsg = `后端服务错误: ${error.response.status} ${error.response.statusText}`
        } else if (error.request) {
          errorMsg = '网络错误: 无法连接到后端服务'
        } else {
          errorMsg = `请求错误: ${error.message}`
        }
        
        console.warn(errorMsg)
      } finally {
        isLoading.value = false
        console.log('加载单词列表完成，当前单词总数:', words.value.length)
      }
    }
    
    // 辅助函数：拼读单词
    async function spellOutWord(wordContent) {
      return new Promise(async (resolve, reject) => {
        try {
          console.log('开始拼读单词:', wordContent);
          
          // 验证selectedVoice是否有效
          const voiceToUse = selectedVoice.value || 'default-voice';
          console.log('使用语音进行拼读:', voiceToUse);
          
          // 使用Hunspell规则获取符合英语学习习惯的拼读形式
          const spelledOutText = getWordPhoneticSpelling(wordContent);
          console.log('使用Hunspell规则的拼读形式:', spelledOutText);
          
          // 首先尝试使用API播放音频
          try {
            // 创建音频URL，使用拼读文本
            const audioUrl = `http://localhost:8082/api/tts/word/${encodeURIComponent(spelledOutText)}?userId=1&voice=${voiceToUse}`;
            console.log('创建拼读音频对象，URL:', audioUrl);
            
            const audio = new Audio(audioUrl);
            
            // 添加标记变量，用于跟踪音频是否已经开始播放
            let hasStartedPlaying = false;
            
            // 配置音频对象
            audio.volume = 1.0; // 设置音量
            
            // 监听音频事件以确定播放是否成功
            audio.addEventListener('canplaythrough', () => {
              console.log('拼读音频可以播放');
            });
            
            audio.addEventListener('error', (error) => {
              console.error('拼读音频API加载失败:', error);
              
              // 如果音频已经开始播放，则忽略加载错误
              if (hasStartedPlaying) {
                console.log('拼读音频已开始播放，忽略加载错误');
                return;
              }
              
              // 尝试使用Web Speech API作为备选方案
              handleSpellOutFallback(spelledOutText, audio, reject, resolve);
            });
            
            // 尝试播放音频
            try {
              await audio.play();
              // 标记音频已开始播放
              hasStartedPlaying = true;
              console.log('拼读音频API播放成功:', wordContent);
              
              // 添加音频结束事件监听以释放资源
              audio.addEventListener('ended', () => {
                console.log('拼读音频播放结束');
                // 清理资源
                audio.src = '';
                audio.remove();
                resolve();
              });
            } catch (playError) {
              console.error('拼读音频API播放失败:', playError);
              // 尝试使用Web Speech API作为备选方案
              handleSpellOutFallback(spelledOutText, audio, reject, resolve);
            }
          } catch (apiError) {
            console.error('拼读API调用异常:', apiError);
            // 尝试使用Web Speech API作为备选方案
            handleSpellOutFallback(spelledOutText, null, reject, resolve);
          }
        } catch (error) {
          console.error('拼读功能异常:', error);
          reject(new Error(`拼读功能异常: ${error.message}`));
        }
      });
    }
    
    // 辅助函数：处理拼读API失败的备选方案
    function handleSpellOutFallback(spelledOutText, audio, reject, resolve) {
      // 清理原有音频资源（如果有）
      if (audio) {
        audio.src = '';
        if (audio.remove) audio.remove();
      }
      
      console.log('拼读API失败，尝试使用Web Speech API作为备选方案');
      
      // 如果浏览器支持Web Speech API，则尝试使用Web Speech API
      if ('speechSynthesis' in window) {
        console.log('浏览器支持Web Speech API，尝试使用其播放拼读');
        
        try {
          // 停止任何正在播放的语音
          window.speechSynthesis.cancel();
          speakText(spelledOutText).then(() => {
            console.log('Web Speech API拼读播放成功');
            resolve();
          }).catch(speechError => {
            console.error('Web Speech API拼读播放失败:', speechError);
            reject(new Error(`拼读播放失败：API和Web Speech API均失败`));
          });
        } catch (webSpeechError) {
          console.error('Web Speech API执行异常:', webSpeechError);
          reject(new Error(`拼读播放失败：API和Web Speech API均失败`));
        }
      } else {
        console.error('浏览器不支持Web Speech API');
        reject(new Error(`拼读播放失败：API失败且浏览器不支持语音合成`));
      }
    }
    
    // 生成模拟单词数据
    const generateMockWords = () => {
      const mockWords = [
        {
          id: 1,
          content: 'hello',
          phonetic: '/həˈloʊ/',
          translation: '你好',
          updatedAt: '2023-06-01T10:00:00Z'
        },
        {
          id: 2,
          content: 'world',
          phonetic: '/wɜːrld/',
          translation: '世界',
          updatedAt: '2023-06-01T10:05:00Z'
        },
        {
          id: 3,
          content: 'learning',
          phonetic: '/ˈlɜːrnɪŋ/',
          translation: '学习',
          updatedAt: '2023-06-01T10:10:00Z'
        },
        {
          id: 4,
          content: 'vocabulary',
          phonetic: '/vəˈkæbjəleri/',
          translation: '词汇',
          updatedAt: '2023-06-01T10:15:00Z'
        },
        {
          id: 5,
          content: 'language',
          phonetic: '/ˈlæŋɡwɪdʒ/',
          translation: '语言',
          updatedAt: '2023-06-01T10:20:00Z'
        },
        {
          id: 6,
          content: 'study',
          phonetic: '/ˈstʌdi/',
          translation: '学习，研究',
          updatedAt: '2023-06-01T10:25:00Z'
        },
        {
          id: 7,
          content: 'practice',
          phonetic: '/ˈpræktɪs/',
          translation: '练习',
          updatedAt: '2023-06-01T10:30:00Z'
        },
        {
          id: 8,
          content: 'improve',
          phonetic: '/ɪmˈpruːv/',
          translation: '提高，改善',
          updatedAt: '2023-06-01T10:35:00Z'
        },
        {
          id: 9,
          content: 'memory',
          phonetic: '/ˈmeməri/',
          translation: '记忆',
          updatedAt: '2023-06-01T10:40:00Z'
        },
        {
          id: 10,
          content: 'progress',
          phonetic: '/ˈprəʊɡres/',
          translation: '进步，进展',
          updatedAt: '2023-06-01T10:45:00Z'
        }
      ]
      
      // 为模拟分页效果，根据当前页码返回不同的数据
      if (currentPage.value > 1) {
        // 生成新的单词数据
        return mockWords.map((word, index) => ({
          ...word,
          id: word.id + (currentPage.value - 1) * 10,
          content: `${word.content}${currentPage.value}`,
          updatedAt: new Date().toISOString()
        }))
      }
      
      return mockWords
    }
    
    // 处理搜索
    const handleSearch = () => {
      // 可以添加防抖处理
      console.log('搜索关键词:', searchKeyword.value)
    }
    
    // 清除搜索
    const clearSearch = () => {
      searchKeyword.value = ''
    }
    
    // 处理单词集筛选
    const handleWordSetChange = () => {
      // 这里可以根据选择的单词集重新加载数据
      loadWords(true)
    }
    
    // 加载更多
    const loadMore = () => {
      if (hasMore.value && !isLoading.value) {
        currentPage.value++
        loadWords()
      }
    }
    
    // 延迟函数
    const delay = (ms) => new Promise(resolve => setTimeout(resolve, ms));
    
    // 播放单词发音
    const playPronunciation = async (word) => {
      try {
        // 实际项目中应调用API获取音频
        console.log('播放单词发音:', word)
        
        // 检查word对象和word.content
        if (!word || !word.content) {
          console.error('单词内容为空:', word)
          alert('无法播放发音：单词内容为空')
          return
        }
        
        console.log('要发音的单词内容:', word.content)
        // 在函数开始时保存shouldSpellOut的值，避免在播放过程中该值发生变化
        const spellOutEnabled = shouldSpellOut.value;
        console.log('是否使用拼读功能:', spellOutEnabled)
        
        // 首先尝试使用API播放音频
        try {
          // 先播放单词的普通发音
          console.log('开始尝试API播放单词发音:', word.content);
          await tryAPI(word.content);
          
          // 如果选择了拼读功能，间隔0.5秒后播放拼读
        if (spellOutEnabled === 1) {
          console.log('单词发音完成(API)，等待0.5秒后播放拼读');
          await delay(500);
          console.log('开始播放拼读(API)');
          await spellOutWord(word.content);
        }
        } catch (apiError) {
          console.log('API调用失败，尝试使用Web Speech API作为备选方案:', apiError.message)
          
          // 如果API调用失败且浏览器支持Web Speech API，则尝试使用Web Speech API
          if ('speechSynthesis' in window) {
            console.log('浏览器支持Web Speech API')
            
            // 立即尝试使用Web Speech API
            try {
              // 停止任何正在播放的语音
              window.speechSynthesis.cancel();
              console.log('开始尝试Web Speech API播放单词发音:', word.content);
              await speakText(word.content);
              
              // 如果选择了拼读功能，间隔0.5秒后播放拼读
                if (spellOutEnabled === 1) {
                  console.log('单词发音完成(Web Speech API)，等待0.5秒后播放拼读');
                  await delay(500);
                  console.log('开始播放拼读(Web Speech API)');
                  
                  // 直接使用speakText播放拼读，避免再次调用可能失败的API
                  // 使用Hunspell规则获取符合英语学习习惯的拼读形式
                  const spelledOutText = getWordPhoneticSpelling(word.content);
                  console.log('开始尝试Web Speech API播放拼读(使用Hunspell规则):', spelledOutText);
                  await speakText(spelledOutText);
                }
            } catch (err) {
              console.error('Web Speech API播放失败:', err);
              // 根据不同错误类型提供更具体的提示
              let errorMsg = '发音播放失败：所有可用的发音方式均失败';
              if (err.message.includes('net::ERR_CONNECTION_REFUSED')) {
                errorMsg = '发音服务未连接：请确认后端服务是否运行';
              }
              alert(errorMsg)
            }
          } else {
            console.error('浏览器不支持Web Speech API')
            alert('发音播放失败：无法连接到语音服务且浏览器不支持语音合成')
          }
        }
      } catch (error) {
        console.error('播放发音失败:', error)
        alert('发音播放失败：' + error.message)
      }
    }
    
    // 辅助函数：使用Web Speech API播放文本
    async function speakText(text) {
      return new Promise((resolve, reject) => {
        try {
          const utterance = new SpeechSynthesisUtterance(text)
          utterance.lang = 'en-US'
          utterance.volume = 1
          utterance.rate = 1
      utterance.pitch = 1
      
      // 合并事件监听器定义，避免重复
      utterance.onstart = () => {
        console.log('开始播放发音:', text)
      }
      utterance.onend = () => {
        console.log('Web Speech API播放完成')
        resolve();
      };
      utterance.onerror = (event) => {
        console.error('Web Speech API错误:', event.error)
        // 保留回退到API的逻辑
        try {
          console.log('尝试回退到API播放')
          tryAPI(text).catch(apiError => {
            // 如果回退也失败，则完全拒绝Promise
            console.error('回退API也失败:', apiError)
            reject(new Error(`Web Speech API错误: ${event.error}，且回退API也失败`));
          })
        } catch (tryError) {
          reject(new Error(`Web Speech API错误: ${event.error}`));
        }
      };
      utterance.onpause = () => {
        console.log('Web Speech API暂停')
      };
      utterance.onresume = () => {
        console.log('Web Speech API恢复')
      };
      
      // 确保语音列表已加载完成
      let voices = speechSynthesis.getVoices();
      
      // 如果语音列表为空，尝试在voiceschanged事件后获取
      if (voices.length === 0) {
        console.log('语音列表为空，尝试等待voiceschanged事件');
        // 使用setTimeout避免死锁
        setTimeout(() => {
          voices = speechSynthesis.getVoices();
          selectVoice(utterance, voices, text);
        }, 100);
      } else {
        selectVoice(utterance, voices, text);
      }
          
          // 播放语音
      speechSynthesis.speak(utterance)
    } catch (err) {
      console.error('Web Speech API执行异常:', err)
      reject(err);
    }
  })
}
    
    // 辅助函数：选择Web Speech API的语音
    function selectVoice(utterance, voices, text) {
      console.log('可用语音数量:', voices.length);
      console.log('可用语音列表:', voices.map(v => ({name: v.name, lang: v.lang})));
      console.log('用户选择的语音:', selectedVoice.value);
      
      // 首先尝试使用用户选择的语音（根据选择的语音ID进行匹配）
      let selectedVoiceMatch = voices.find(voice => 
        // 尝试多种匹配方式，提高兼容性
        (voice.name && voice.name.toLowerCase().includes(selectedVoice.value.toLowerCase())) ||
        (voice.lang && voice.lang.toLowerCase().includes(selectedVoice.value.toLowerCase()))
      );
      
      // 如果没有找到匹配的语音，尝试查找英语语音作为备选
      if (!selectedVoiceMatch) {
        console.log('未找到匹配用户选择的语音，尝试查找英语语音');
        selectedVoiceMatch = voices.find(voice => 
          voice.lang && voice.lang.toLowerCase().includes('en') || 
          voice.name && voice.name.toLowerCase().includes('english')
        );
      }
      
      // 如果仍然没有找到英语语音，尝试查找默认语音或第一个可用语音
      if (!selectedVoiceMatch) {
        const defaultVoice = voices.find(voice => voice.default);
        if (defaultVoice) {
          selectedVoiceMatch = defaultVoice;
          console.log('使用默认语音:', selectedVoiceMatch.name);
        } else if (voices.length > 0) {
          selectedVoiceMatch = voices[0];
          console.log('使用第一个可用语音:', selectedVoiceMatch.name);
        } else {
          console.log('没有可用的语音，使用浏览器默认设置');
          // 不需要设置语音，让浏览器使用默认设置
          return;
        }
      } else {
        console.log('使用匹配语音:', selectedVoiceMatch.name);
      }
      
      // 设置选择的语音
      if (selectedVoiceMatch) {
        utterance.voice = selectedVoiceMatch;
      }
    }
    
    // 辅助函数：尝试使用API播放音频
      async function tryAPI(wordContent) {
        return new Promise((resolve, reject) => {
        try {
            console.log('尝试API调用:', wordContent)
            console.log('使用语音:', selectedVoice.value)
            // 从后端配置发现服务运行在8082端口，而不是8080端口
            
            // 确保在创建音频对象前验证并应用用户选择的语音
            // 1. 验证selectedVoice是否有效
            const voiceToUse = selectedVoice.value || 'default-voice';
            console.log('验证语音参数:', voiceToUse);
            
            // 2. 在API请求URL中明确应用语音参数
            // 这是语音参数实际被后端接收并使用的关键步骤
            const audioUrl = `http://localhost:8082/api/tts/word/${wordContent}?userId=1&voice=${voiceToUse}`;
            console.log('创建音频对象，URL中包含语音参数:', audioUrl);
            
            const audio = new Audio(audioUrl);
            
            // 添加标记变量，用于跟踪音频是否已经开始播放
            let hasStartedPlaying = false
            
            // 配置音频对象
            audio.volume = 1.0; // 设置音量
          
          // 监听音频事件以确定播放是否成功
          audio.addEventListener('canplaythrough', () => {
            console.log('音频可以播放')
          })
          
          audio.addEventListener('error', (error) => {
            console.error('音频API加载失败:', error);
            
            // 详细记录错误对象的所有属性，便于调试
            let errorDetails = {};
            for (let prop in error) {
              if (error.hasOwnProperty(prop) && typeof error[prop] !== 'function') {
                errorDetails[prop] = error[prop];
              }
            }
            console.log('音频加载错误详情:', errorDetails);
            
            // 如果音频已经开始播放，则忽略加载错误
            if (hasStartedPlaying) {
              console.log('音频已开始播放，忽略加载错误');
              return; // 不调用reject，避免Promise被拒绝
            }
            
            // 提供更具体的错误信息
            let errorMsg = '音频API加载失败';
            
            // 1. 检查媒体错误类型
            if (error.type === 'error' && error.currentTarget && error.currentTarget.error) {
              const mediaError = error.currentTarget.error;
              switch (mediaError.code) {
                case mediaError.MEDIA_ERR_ABORTED:
                  errorMsg = '音频加载被中止';
                  break;
                case mediaError.MEDIA_ERR_NETWORK:
                  errorMsg = '网络错误导致音频加载失败';
                  break;
                case mediaError.MEDIA_ERR_DECODE:
                  errorMsg = '音频解码失败';
                  break;
                case mediaError.MEDIA_ERR_SRC_NOT_SUPPORTED:
                  errorMsg = '音频格式不支持或API端点返回了无效内容';
                  break;
                default:
                  errorMsg = '音频加载失败';
              }
            } 
            // 2. 检查连接拒绝错误（端口已更新为8082）
            else if (error.message && error.message.includes('ERR_CONNECTION_REFUSED')) {
              errorMsg = '后端服务未连接：请确认TTS服务是否运行在8082端口';
            }
            // 3. 检查其他可能的错误
            else if (error.target && error.target.networkState === 3) {
              errorMsg = '网络错误：无法连接到音频源';
            }
            // 4. 检查NotSupportedError
            else if (error.currentTarget && error.currentTarget.error && 
                     error.currentTarget.error.name === 'NotSupportedError') {
              errorMsg = '不支持的音频源：后端返回的音频格式不被浏览器支持';
            }
            
            // 5. 添加上下文信息
            errorMsg += ` (URL: http://localhost:8082/api/tts/word/${wordContent}?userId=1&voice=${selectedVoice.value})`;
            errorMsg += '\n\n提示：您可以尝试直接在浏览器中访问该URL，查看后端服务是否正确响应。';
            
            reject(new Error(errorMsg))
          })
          
          // 尝试播放音频
          audio.play()
            .then(() => {
              // 标记音频已开始播放
              hasStartedPlaying = true
              console.log('音频API播放成功:', wordContent)
              // 添加音频结束事件监听以释放资源
              audio.addEventListener('ended', () => {
                console.log('音频播放结束')
                // 清理资源
                audio.src = '';
                audio.remove();
                resolve()
              })
            })
            .catch(error => {
              console.error('音频API播放失败:', error)
              // 针对NotSupportedError提供更详细的处理
              let errorMsg = `音频播放失败: ${error.message}`;
              if (error.name === 'NotSupportedError' || error.message.includes('no supported source')) {
                errorMsg += '\n这通常表示后端返回的音频格式不被浏览器支持，或返回了无效的音频数据。' +
                            '\n建议检查后端TTS服务的音频输出格式设置。' +
                            '\n系统将自动尝试使用Web Speech API作为备选方案。';
              }
              // 清理资源
              audio.src = '';
              audio.remove();
              reject(new Error(errorMsg))
            })
        } catch (apiError) {
          console.error('API调用失败:', apiError)
          reject(new Error(`API调用异常: ${apiError.message}`))
        }
      })
    }
    
    // 显示更多选项
    const showMoreOptions = (word) => {
      selectedWord.value = word
      showPopup.value = true
    }
    
    // 关闭操作菜单
    const closeActionPopup = () => {
      showPopup.value = false
    }
    
    // 编辑单词
    const handleEditWord = () => {
      closeActionPopup()
      // 在实际项目中，这里应该跳转到编辑页面
      alert('编辑单词功能开发中')
    }
    
    // 添加到单词集
    const handleAddToWordSet = () => {
      closeActionPopup()
      // 实际项目中应打开单词集选择界面
      alert('添加到单词集功能开发中')
    }
    
    // 删除单词
    const handleDeleteWord = () => {
      closeActionPopup()
      
      if (confirm(`确定要删除单词 "${selectedWord.value.content}" 吗？`)) {
        // 实际项目中应调用API删除单词
        console.log('删除单词:', selectedWord.value.id)
        words.value = words.value.filter(word => word.id !== selectedWord.value.id)
        alert('删除成功')
      }
    }
    
    // 页面跳转
    const goToAddWord = () => {
      router.push('/pages/word/AddWord')
    }
    
    const goToEditWord = (id) => {
      router.push(`/pages/word/EditWord?id=${id}`)
    }
    
    const goToWordDetail = (id) => {
      router.push(`/pages/word/WordDetail?id=${id}`)
    }
    
    // 处理滚动加载更多
    const handleScroll = () => {
      if ((window.innerHeight + window.scrollY) >= document.body.offsetHeight - 100) {
        loadMore()
      }
    }
    
    // 组件挂载时加载数据
    onMounted(() => {
      loadWords()
      window.addEventListener('scroll', handleScroll)
      // 加载Hunspell规则
      loadHunspellRules().catch(error => {
        console.error('Failed to load Hunspell rules during initialization:', error);
      })
    })
    
    // 组件卸载时移除事件监听
    onUnmounted(() => {
      window.removeEventListener('scroll', handleScroll)
    })
    
    return {
      words,
      searchKeyword,
      sortBy,
      currentWordSet,
      wordSets,
      hasMore,
      isLoading,
      displayedWords,
      showPopup,
      availableVoices,
      selectedVoice, 
      handleSpellOutChange,
      handleSearch,
      clearSearch,
      handleWordSetChange,
      loadMore,
      playPronunciation,
      showMoreOptions,
      closeActionPopup,
      handleEditWord,
      handleAddToWordSet,
      handleDeleteWord,
      goToAddWord,
      goToEditWord,
      goToWordDetail
    }
  }
}
</script>

<style scoped>
.word-list-container {
  padding: 16px;
  background-color: #f5f5f5;
  min-height: 100vh;
}

.header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 20px;
}

.title {
  font-size: 24px;
  font-weight: bold;
  color: #333;
  margin: 0;
}

.btn-add {
  background-color: #07c160;
  color: #fff;
  border-radius: 6px;
  padding: 8px 16px;
  display: flex;
  align-items: center;
  gap: 4px;
  border: none;
  cursor: pointer;
}

.btn-add:hover {
  background-color: #06ad56;
}

.search-filter-section {
  margin-bottom: 20px;
}

.search-box {
  display: flex;
  align-items: center;
  background-color: #fff;
  border-radius: 8px;
  padding: 0 12px;
  margin-bottom: 12px;
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
}

.search-icon {
  margin-right: 8px;
  font-size: 18px;
  color: #999;
}

.search-input {
  flex: 1;
  height: 40px;
  border: none;
  outline: none;
  font-size: 14px;
}

.clear-search-btn {
  background: none;
  border: none;
  padding: 4px;
  cursor: pointer;
  font-size: 16px;
  color: #999;
}

.filter-options {
  display: flex;
  justify-content: space-between;
  align-items: center;
  background-color: #fff;
  border-radius: 8px;
  padding: 12px;
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
}

.filter-select {
  flex: 1;
  padding: 8px;
  border: 1px solid #ddd;
  border-radius: 6px;
  background-color: #fff;
  font-size: 14px;
}

.sort-options {
  display: flex;
  gap: 8px;
}

.sort-btn {
  background-color: #f5f5f5;
  border-radius: 6px;
  padding: 6px 12px;
  font-size: 14px;
  border: none;
  cursor: pointer;
}

.sort-btn.active {
  background-color: #e0f7fa;
  color: #1989fa;
}

.sort-btn:hover {
  background-color: #ebebeb;
}

.sort-btn.active:hover {
  background-color: #d0effa;
}

.word-list {
  margin-bottom: 20px;
}

.word-item {
  background-color: #fff;
  border-radius: 10px;
  padding: 16px;
  margin-bottom: 12px;
  display: flex;
  justify-content: space-between;
  align-items: center;
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
  transition: transform 0.2s ease;
  cursor: pointer;
}

.word-item:hover {
  transform: translateY(-2px);
  box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
}

.word-main {
  flex: 1;
}

.word-content {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 4px;
}

.word-text {
  font-size: 18px;
  font-weight: bold;
  color: #333;
}

.word-phonetic {
  font-size: 14px;
  color: #999;
  font-style: italic;
}

.word-translation {
  font-size: 14px;
  color: #666;
}

.word-actions {
  display: flex;
  gap: 8px;
}

.btn-pronounce, .btn-more {
  background: none;
  border: none;
  padding: 8px;
  cursor: pointer;
  font-size: 18px;
}

.empty-state {
  text-align: center;
  padding: 60px 20px;
  color: #999;
}

.empty-icon {
  font-size: 60px;
  margin-bottom: 16px;
}

.empty-text {
  font-size: 16px;
  margin: 16px 0 8px 0;
}

.empty-subtext {
  font-size: 14px;
  color: #ccc;
  margin: 0;
}

.load-more {
  text-align: center;
  padding: 16px;
  color: #666;
  font-size: 14px;
  cursor: pointer;
}

.load-more:hover {
  color: #333;
}

/* 模态框样式 */
.modal-overlay {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background-color: rgba(0, 0, 0, 0.5);
  display: flex;
  align-items: flex-end;
  justify-content: center;
  z-index: 1000;
}

.popup-content {
  background-color: #fff;
  border-top-left-radius: 16px;
  border-top-right-radius: 16px;
  width: 100%;
  max-width: 600px;
  max-height: 80vh;
  overflow-y: auto;
}

.popup-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 16px;
  border-bottom: 1px solid #f5f5f5;
}

.popup-title {
  font-size: 16px;
  font-weight: bold;
  color: #333;
  margin: 0;
}

.close-popup-btn {
  background: none;
  border: none;
  padding: 4px;
  cursor: pointer;
  font-size: 20px;
  color: #999;
}

.popup-actions {
  padding: 8px 0;
}

.popup-action-item {
  width: 100%;
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 16px 24px;
  background: none;
  border: none;
  font-size: 16px;
  color: #333;
  cursor: pointer;
  text-align: left;
}

.popup-action-item:hover {
  background-color: #f5f5f5;
}

.popup-action-item.danger {
  color: #e64340;
}

.popup-action-item.danger:hover {
  background-color: #fff0f0;
}

.action-icon {
  font-size: 20px;
}

.cancel-btn {
  width: 90%;
  margin: 16px auto;
  padding: 12px;
  background-color: #f5f5f5;
  border: none;
  border-radius: 8px;
  font-size: 16px;
  color: #333;
  cursor: pointer;
}

/* 语音选择样式 */
    .voice-selection {
      display: flex;
      align-items: center;
      margin-right: 16px;
    }
    
    .voice-selection label {
      margin-right: 8px;
      font-size: 14px;
      color: #666;
      white-space: nowrap;
    }
    
    .voice-select {
      padding: 6px 12px;
      border: 1px solid #ddd;
      border-radius: 6px;
      font-size: 14px;
      background-color: #fff;
      cursor: pointer;
      outline: none;
      transition: border-color 0.3s;
    }
    
    .voice-select:hover {
      border-color: #999;
    }
    
    .voice-select:focus {
      border-color: #4CAF50;
    }
    
    /* 拼读选择样式 */
    .spell-selection {
      display: flex;
      align-items: center;
      margin-right: 16px;
    }
    
    .spell-selection label {
      margin-right: 8px;
      font-size: 14px;
      color: #666;
      white-space: nowrap;
    }
    
    .spell-select {
      padding: 6px 12px;
      border: 1px solid #ddd;
      border-radius: 6px;
      font-size: 14px;
      background-color: #fff;
      cursor: pointer;
      outline: none;
      transition: border-color 0.3s;
    }
    
    .spell-select:hover {
      border-color: #999;
    }
    
    .spell-select:focus {
      border-color: #4CAF50;
    }
    
    /* 确保选择语音、是否拼读和添加按钮在一行 */
    .header-actions {
      display: flex;
      align-items: center;
      flex-wrap: nowrap;
      gap: 8px;
    }
    
    @media (max-width: 768px) {
      .header-actions {
        flex-wrap: wrap;
        justify-content: flex-end;
        gap: 4px;
      }
      
      .voice-selection {
        margin-right: 0;
        margin-bottom: 8px;
      }
      
      .spell-selection {
        margin-right: 0;
        margin-bottom: 8px;
      }
    }

.cancel-btn:hover {
  background-color: #ebebeb;
}

/* 响应式设计 */
@media (max-width: 768px) {
  .filter-options {
    flex-direction: column;
    gap: 12px;
    align-items: stretch;
  }
  
  .sort-options {
    justify-content: center;
  }
}
</style>